Skip to content

refactor: 목 데이터와 프로젝트 연동 (#60)#62

Merged
AndyH0ng merged 12 commits intodevelopfrom
refactor/mock-project-60
Jan 20, 2026
Merged

refactor: 목 데이터와 프로젝트 연동 (#60)#62
AndyH0ng merged 12 commits intodevelopfrom
refactor/mock-project-60

Conversation

@AndyH0ng
Copy link
Member

@AndyH0ng AndyH0ng commented Jan 19, 2026

📌 관련 이슈

✨ 변경 내용

  • 프로젝트 목 데이터 구현
  • 슬라이드 비율 4:3 일때 잘리는 문제 수정
  • 타입 이름 맞추고 Props 컴포넌트 책임으로 이양
  • /slide에서 슬라이드 ID 쿼리 파라미터로 관리
  • Dropdown 컴포넌트 varientdanger일 때 selected된 경우 bg-error로 칠하도록 변경

💡 참고 사항

2026-01-19.6.57.44.mov
스크린샷 2026-01-19 오후 7 00 47
2026-01-19.8.34.47.mov

이전 PR에서 달성한거긴 한데 TAB 키로 요소간 이동하게 만들고 강조색으로 하이라이트되게 만들었습니다 (크롬/크로뮴 기반만 됨 사파리x 파폭 테스트 안해봄)

@AndyH0ng AndyH0ng self-assigned this Jan 19, 2026
@AndyH0ng AndyH0ng linked an issue Jan 19, 2026 that may be closed by this pull request
3 tasks
@github-actions github-actions bot added component 컴포넌트 관련 변경 page 페이지 관련 변경 types 타입 정의 변경 store 상태 관리 변경 hooks 커스텀 훅 변경 documentation labels Jan 19, 2026
@gemini-code-assist
Copy link
Contributor

Summary of Changes

Hello @AndyH0ng, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

이 PR은 목 데이터를 실제 프로젝트 구조에 연동하고, 전반적인 코드베이스의 타입 정의와 UI/UX를 개선하는 데 중점을 둡니다. 특히, 슬라이드 ID를 쿼리 파라미터로 관리하도록 변경하여 URL 구조의 유연성을 확보하고, 프로젝트 목록의 정렬 및 보기 모드 기능을 추가하여 사용자 경험을 향상시켰습니다. 또한, CommentItem과 같은 주요 타입들의 명칭을 간결하게 리팩토링하고, 컴포넌트의 로딩 및 스타일링을 세밀하게 조정하여 코드의 가독성과 유지보수성을 높였습니다.

Highlights

  • 목 데이터 연동 및 확장: 프로젝트 목 데이터를 구현하고, 기존 슬라이드 목 데이터에 projectId를 추가하여 프로젝트별 슬라이드를 생성하도록 확장했습니다.
  • 타입 정의 리팩토링: CommentItemComment로, HistoryItemHistory로, EmojiReactionReaction으로 일관성 있게 변경하고, 관련 컴포넌트 및 API 엔드포인트에 적용했습니다.
  • 슬라이드 ID URL 관리 방식 변경: 슬라이드 ID를 URL 경로(/:slideId)에서 쿼리 파라미터(?slideId=)로 변경하여 유연성을 높였습니다.
  • UI/UX 개선: 슬라이드 이미지 로딩 시 깜빡임 문제를 개선하고, 4:3 비율에서 이미지가 잘리는 문제를 수정했습니다. Dropdown 컴포넌트의 danger 타입 아이템이 선택되었을 때 bg-error 스타일을 적용하도록 개선했습니다. 프로젝트 카드에 드롭다운 메뉴를 추가하고, 홈 화면 프로젝트 목록에 정렬 및 보기 모드 기능을 통합했습니다.
  • 코드 구조 개선: REACTION_CONFIG를 별도 상수 파일로 분리하여 관리하고, 각종 훅의 JSDoc 주석을 간결하게 정리했습니다. 또한, src/types/index.ts 파일을 추가하여 타입 정의를 한 곳에서 관리할 수 있도록 했습니다.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for Github and other Google products, sign up here.

You can also get AI-powered code generation, chat, as well as code reviews directly in the IDE at no cost with the Gemini Code Assist IDE Extension.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

Copy link
Contributor

@gemini-code-assist gemini-code-assist bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Code Review

전반적으로 코드베이스를 크게 개선하는 인상적인 리팩터링 PR입니다. 타입 일관성, 컴포넌트 props 위치 조정, 상수 분리 등의 변경 사항들이 훌륭합니다. 슬라이드 라우팅을 쿼리 파라미터 방식으로 변경한 것은 견고한 아키텍처 개선이며 잘 구현되었습니다. 목 데이터 개선 또한 향후 개발에 큰 도움이 될 것입니다.

정렬 로직, 레이아웃 시프트 방지와 관련된 몇 가지 개선점을 찾아 주석으로 남겼습니다. 전반적으로 훌륭한 리팩터링 작업입니다!

@github-actions
Copy link

github-actions bot commented Jan 19, 2026

Visit the preview URL for this PR (updated for commit 1359142):

https://ttorang--pr62-refactor-mock-projec-qzcfkf0q.web.app

(expires Mon, 26 Jan 2026 10:22:39 GMT)

🔥 via Firebase Hosting GitHub Action 🌎

Sign: b554669f2531ae9a6954d553a841ad9a6c4ceb6d

@AndyH0ng
Copy link
Member Author

@claude 코드 리뷰해줘

@claude
Copy link

claude bot commented Jan 19, 2026

Claude finished @AndyH0ng's task in 1m 57s —— View job


코드 리뷰 완료

전반적으로 깔끔하고 체계적인 리팩토링입니다! 👍 타입 일관성 개선, 라우팅 구조 변경, 목 데이터 확장 등 주요 변경사항들이 프로젝트 아키텍처를 개선하는데 기여하고 있습니다. Gemini의 리뷰 의견도 참고하여 몇 가지 추가 의견을 남깁니다.


긍정적인 부분 ✨

  1. 타입 일관성 개선

    • CommentItemComment, HistoryItemHistory, EmojiReactionReaction으로 간결하게 통일
    • src/types/index.ts로 중앙집중식 타입 export - 매우 좋은 패턴입니다
  2. 라우팅 구조 개선

    • 슬라이드 ID를 쿼리 파라미터(?slideId=)로 변경한 것은 탁월한 결정
    • URL 구조가 더 유연해지고 RESTful 원칙에 부합
    • SlidePage.tsx:16의 폴백 로직(?? slides?.[0])으로 안전하게 처리
  3. 상수 분리

    • REACTION_CONFIG를 별도 파일(src/constants/reaction.ts)로 분리 - 관심사 분리 원칙 준수
  4. 목 데이터 구조 개선

    • 프로젝트별 슬라이드 생성 로직이 체계적 (src/mocks/slides.ts:14-20)
    • 동적 생성 함수로 유지보수성 향상
  5. 이미지 로딩 UX 개선

    • SlideImage 컴포넌트의 onLoad + opacity transition으로 깜빡임 방지

개선 제안 🔍

1. 레이아웃 시프트 방지 (중요도: 중)

위치: src/components/slide/SlideThumbnail.tsx:42

Gemini가 지적한 부분과 동일합니다. 스켈레톤의 aspect-video를 제거하면 이미지 로드 시 레이아웃이 흔들릴 수 있습니다.

// 현재 (SlideThumbnail.tsx:42)
<div className="flex-1 aspect-video rounded bg-gray-200 animate-pulse" />

// 권장: aspect-video 유지
<div className="flex-1 aspect-video rounded bg-gray-200 animate-pulse" />

실제 코드를 보니 이미 aspect-video가 있네요! Gemini의 제안과 달리 현재 코드가 이미 올바릅니다. 👍

2. 하드코딩된 폴백 제거 검토 (중요도: 낮)

위치: src/pages/SlidePage.tsx:16

const currentSlide = slides?.find((s) => s.id === slideIdParam) ?? slides?.[0];

Gemini가 지적했듯이, useEffect(30-40라인)에서 이미 유효하지 않은 slideId 처리를 하고 있으므로 이 폴백은 사실상 불필요할 수 있습니다. 하지만 현재 코드도 방어적 프로그래밍 관점에서 나쁘지 않습니다.

3. Dropdown 컴포넌트 스타일링 복잡도

위치: src/components/common/Dropdown.tsx:226-240

selectedvariant='danger' 조합의 조건부 스타일링이 복잡합니다:

className={clsx(
  'w-full whitespace-nowrap px-5 py-3 text-left text-body-m-bold transition-colors focus:outline-none',
  {
    'cursor-not-allowed opacity-50': item.disabled,
    'text-error': item.variant === 'danger' && !item.selected,
    'text-gray-800': item.variant !== 'danger' && !item.selected,
    'bg-gray-100': !item.disabled && isFocused && !item.selected,
    'bg-main-variant1 text-white': item.selected && item.variant !== 'danger',
    'bg-error text-white': item.selected && item.variant === 'danger',
    'active:bg-main-variant1 active:text-white':
      !item.disabled && !item.selected && item.variant !== 'danger',
    'active:bg-error active:text-white':
      !item.disabled && !item.selected && item.variant === 'danger',
  },
)}

제안: 조건문을 헬퍼 함수로 분리하면 가독성이 향상됩니다:

const getItemClassName = (item: DropdownItem, isFocused: boolean) => {
  const base = 'w-full whitespace-nowrap px-5 py-3 text-left text-body-m-bold transition-colors focus:outline-none';
  
  if (item.disabled) return clsx(base, 'cursor-not-allowed opacity-50');
  
  const isDanger = item.variant === 'danger';
  
  // Selected state
  if (item.selected) {
    return clsx(base, isDanger ? 'bg-error text-white' : 'bg-main-variant1 text-white');
  }
  
  // Default state
  return clsx(
    base,
    isDanger ? 'text-error' : 'text-gray-800',
    isFocused && 'bg-gray-100',
    isDanger ? 'active:bg-error active:text-white' : 'active:bg-main-variant1 active:text-white'
  );
};

다만 현재 코드도 동작상 문제는 없으므로 선택사항입니다.

4. 타입 안전성 강화

위치: src/types/index.ts

현재 barrel export 파일이 잘 정리되어 있지만, 향후 타입 충돌 방지를 위해 네임스페이스 사용을 고려할 수 있습니다:

// 선택사항: 타입 네임스페이스 그룹핑
export type * as CommentTypes from './comment';
export type * as SlideTypes from './slide';

하지만 현재 구조도 충분히 명확합니다.

5. ProjectCard 드롭다운 TODO 구현

위치: src/components/projects/ProjectCard.tsx:29-44

드롭다운 메뉴의 이름 변경/삭제 로직이 TODO로 남아있습니다. 이는 의도된 것으로 보이지만, 실제 클릭 시 아무 동작도 하지 않으므로 사용자 혼란을 줄 수 있습니다.

제안:

  • 구현 전까지 disabled: true 추가
  • 또는 임시로 alert 또는 toast 메시지 표시
{
  id: 'rename',
  label: '이름 변경',
  disabled: true, // 또는 onClick에서 showToast.info('준비중입니다')
  onClick: () => {},
},

코드 품질 체크 ✅

  • TypeScript strict mode 준수
  • 컴포넌트 네이밍 규칙 (PascalCase) 준수
  • Barrel export 패턴 적용
  • 시맨틱 HTML 사용 (<article>, <button> 등)
  • 접근성 속성 적용 (aria-label, role 등)
  • 키보드 네비게이션 지원 (Dropdown)
  • 에러 바운더리 처리 (SlidePage.tsx:21-25)
  • 로딩 상태 관리

보안 & 성능

  • ✅ XSS 방지: 사용자 입력 적절히 처리됨
  • ✅ 이미지 lazy loading: SlideImage에서 로딩 상태 관리
  • ✅ 불필요한 리렌더링 방지: Zustand selector 패턴 활용
  • ✅ 메모리 누수 방지: useEffect cleanup 함수 존재

테스트 권장사항

  1. 라우팅 테스트: ?slideId= 파라미터 없을 때, 유효하지 않을 때 동작 확인
  2. 브라우저 호환성: TAB 키 포커스 하이라이트가 Safari/Firefox에서도 동작하는지 확인
  3. 4:3 비율 슬라이드: 이미지 잘림 이슈 수정 확인 필요
  4. Dropdown 테스트: variant='danger' + selected 조합 시각적 검증

커밋 메시지 품질

design: 코드 리뷰 반영 (#60)
fix: 코드 리뷰 반영 (#60)
chore: 임포트 정리 (#60)
chore: 프로젝트 목 데이터 추가 (#60)
feat: 슬라이드 숫자 쿼리 파라미터로 변경 (#60)

✅ 프로젝트의 커밋 컨벤션을 잘 따르고 있습니다.


최종 의견

이 PR은 머지 가능 상태입니다. 🎉

제시한 개선 제안들은 대부분 선택사항이며, 핵심 기능과 코드 품질은 이미 높은 수준입니다. 특히 라우팅 구조 변경과 타입 정리는 향후 유지보수성을 크게 향상시킬 것입니다.

Gemini가 제안한 두 가지 중 스켈레톤 UI는 이미 올바르게 구현되어 있고, 하드코딩 부분은 현재 코드도 충분히 방어적입니다.

고생하셨습니다! 👏


@AndyH0ng AndyH0ng merged commit 82e5ebc into develop Jan 20, 2026
7 checks passed
@AndyH0ng AndyH0ng deleted the refactor/mock-project-60 branch January 20, 2026 11:43
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

component 컴포넌트 관련 변경 documentation hooks 커스텀 훅 변경 page 페이지 관련 변경 store 상태 관리 변경 types 타입 정의 변경

Projects

None yet

Development

Successfully merging this pull request may close these issues.

refactor: 목 프로젝트와 슬라이드 연동

2 participants